import React, {
    Fragment,
    PureComponent
} from 'react';

import {
    View,
    Text,
    StyleSheet,
    FlatList,
    FlatListProps,
    ActivityIndicator
} from 'react-native';

import Scroll from './scroll';

interface Props extends FlatListProps<any> {
    limit: number,
    lazy: boolean,
    onLoadPage: Function,
    onLoadTop: Function,
    loadingColor:string,
    emptyFull:boolean,
    onScroll():void
}

interface State {
    width: number,
    height: number,
    success:boolean,
    loading: boolean,
    refreshing: boolean,
    isLastPage: boolean,
    isFirst:boolean
}

class ListView extends PureComponent <Props, State> {
    state = {
        width: 0,
        height: 0,
        isFirst:true,
        success:true,
        loading: false,
        refreshing: false,
        isLastPage: false
    }

    static scroll = Scroll;

    static defaultProps = {
        data: [],
        limit: 20,
        lazy: false,
        emptyFull:true,
        loadingColor:`#FF0080`,
        onLoadTop: () => null,
        onLoadPage: () => null,
        onScroll:() => null,
        ListEmptyComponent: null
    }

    componentDidMount() {
        this.resetRefresh();
    }

    public resetRefresh = () => {
        setTimeout(this._onRefresh)
    }

    _onLayout = async (layout: any) => {
        const {
            width,
            height
        } = layout;

        this.setState({
            width, height
        })
    }

    _onRefresh = () => {
        const {
            onLoadTop
        } = this.props;

        const {
            loading
        } = this.state;

        if (loading) {
            return false
        }

        this.setState({
            success:true,
            isLastPage: false,
            refreshing: true
        })

        onLoadTop(this._onRefreshEnd);
    }

    _onRefreshEnd = (
        list: Array<any> = [],
        success: boolean = true
    ) => {
        const {
            length
        } = list;

        const {
            limit
        } = this.props;

        const _isLastPage = (
            success ? (length < limit) : false
        )

        this.setState({
            isFirst:false,
            success:success,
            refreshing: false,
            isLastPage: _isLastPage
        })
    }

    _onEndReached = () => {
        const {
            onLoadPage
        } = this.props;

        const {
            loading,
            isLastPage
        } = this.state;

        if (loading) {
            return false
        }

        if (isLastPage) {
            return false
        }

        this.setState({
            loading: true
        })

        onLoadPage(this._onEndReachedEnd);
    }

    _onEndReachedEnd = (
        list: Array<any> = [],
        success: boolean = true
    ) => {
        const {
            length
        } = list;

        const {
            limit
        } = this.props;

        const _isLastPage = (
            success ? (length < limit) : false
        )

        this.setState({
            success:success,
            loading: false,
            isLastPage: _isLastPage
        })
    }

    _ListEmptyComponent = () => {
        const {

            width,
            height,
            success,
            loading,
            isFirst,
            refreshing
        } = this.state;

        const {
            emptyFull,
            loadingColor,
            ListEmptyComponent
        } = this.props

        if(height <= 0) {
            return null;
        }

        const _size = {
            width: width,
            height: height
        }

        const _styles = [
            styles.centerContent
        ];

        if(emptyFull) {
            _styles.push(_size);
        };

        const _Node:any = (
            (loading || refreshing) && isFirst
        ) ? (
            <ActivityIndicator
                size="large"
                color={loadingColor}
            />
        ) : ListEmptyComponent;

        const props = success ? undefined : {
            title:`-- Network Error --`
        }
        return (
            <View style={_styles}>
                {React.cloneElement(_Node,props)}
            </View>
        )
    }

    _ListFooterComponent = () => {
        const {
            isLastPage,
            refreshing
        } = this.state;

        const {
            data,
            limit,
            loadingColor
        } = this.props;

        const {
            length
        } = data || [];

        if (refreshing || !length) {
            return null;
        }

        if (limit > length) {
            return (
                <View style={styles.fillStyle}/>
            )
        }

        const _textStyle = [
            styles.loadingText,
        ]

        _textStyle.push({
            color:loadingColor
        })

        return (
            <View style={styles.listFooter}>
                {isLastPage ? (
                    <Text style={styles.noData}>
                        -- No Data --
                    </Text>
                ) : (
                    <Fragment>
                        <ActivityIndicator color={loadingColor}/>
                        <Text style={_textStyle}>Loading..</Text>
                    </Fragment>
                )}
            </View>
        )
    }

    get data(): Array<any> {
        const {
            data
        } = this.props;
        const _data = data || [];
        return _data.map((item, i) => ({
            ...item,
            key: `row_key_${i}`
        }))
    }

    get contentContainerStyle() {
        const {
            length
        } = this.data;
        const {
            contentContainerStyle
        } = this.props;
        return length > 0 ?
            contentContainerStyle : null;
    }

    get scrollEnabled() {
        const {
            isFirst,
            refreshing
        } = this.state;

        const {
            scrollEnabled = true
        } = this.props;

        if(isFirst) {
            return true
        }

        if(refreshing) {
            return false
        }

        return scrollEnabled;
    }

    render() {
        const {
            lazy,
            onScroll,
            ...rest
        } = this.props;

        const {
            isFirst,
            refreshing
        } = this.state;

        return (
            <Scroll
                lazy={lazy}
                onScroll={onScroll}
                onLayout={this._onLayout}
            >
                <FlatList
                    {...rest}
                    data={this.data}
                    onEndReachedThreshold={.2}
                    onRefresh={this._onRefresh}
                    removeClippedSubviews={!lazy}
                    scrollEnabled={this.scrollEnabled}
                    onEndReached={this._onEndReached}
                    refreshing={!isFirst && refreshing}
                    ListEmptyComponent={this._ListEmptyComponent}
                    ListFooterComponent={this._ListFooterComponent}
                    contentContainerStyle={this.contentContainerStyle}
                />
            </Scroll>
        )
    }
}

export default ListView;

const styles = StyleSheet.create({
    listFooter: {
        alignItems: `center`,
        flexDirection: `row`,
        justifyContent: `center`,
        paddingVertical: 16
    },
    loadingText: {
        fontSize: 14,
        paddingLeft: 8
    },
    centerContent: {
        alignItems: `center`,
        justifyContent: `center`
    },
    noData: {
        fontSize: 14,
        color: `#545454`,
    },
    fillStyle: {
        height: 16
    }
}) as any;